home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 034 (1987-11-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 034 (1987-11-15)(Ossowski, Stefan)(DE)(PD).adf / Chess / chess.c < prev    next >
C/C++ Source or Header  |  1989-01-18  |  47KB  |  1,689 lines

  1. /*
  2.     C source for CHESS               Rev. 3-10-87
  3.  
  4.     Written by John Stanback (hplabs!hpfcla!hpisla!hpltca!jhs)
  5.  
  6. */ 
  7. #define AMIGA
  8. #ifdef AMIGA
  9. char version[] = "Chess 1.0 John Stanback, Amiga port: Bob Leivian";
  10. #endif
  11. #include <stdio.h>
  12. #include "curses.h"
  13.  
  14. #define neutral 0
  15. #define white 1
  16. #define black 2 
  17. #define no_piece 0
  18. #define pawn 1
  19. #define knight 2
  20. #define bishop 3
  21. #define rook 4
  22. #define queen 5
  23. #define king 6
  24. #define px " PNBRQK"
  25. #define qx " pnbrqk"
  26. #define rx "12345678"
  27. #define cx "abcdefgh"
  28. #define check 0x0001
  29. #define capture 0x0002
  30. #define draw 0x0004
  31. #define promote 0x0010
  32. #define incheck 0x0020
  33. #define epmask 0x0040
  34. #define exact 0x0100
  35. #define pwnthrt 0x0200
  36. #define true 1
  37. #define false 0
  38.  
  39. struct leaf
  40.   {
  41.     short f,t,score,reply;
  42.     unsigned short flags;
  43.   };
  44.  
  45. char mvstr1[5],mvstr2[5];
  46. struct leaf Tree[2000],*root;
  47. short TrPnt[30];
  48. short row[64],col[64],locn[8][8],indx[64],svalue[64];
  49. short PieceList[3][16],PieceCnt[3];
  50. short castld[3],kingmoved[3],mtl[3],pmtl[3],emtl[3],hung[3];
  51. short mate,post,xkillr,ykillr,opponent,computer,Sdepth;
  52. long time();
  53. long time0 = 0;
  54. int response_time,extra_time,timeout,et,et0;
  55. short quit,reverse,bothsides,InChk,player;
  56. int NodeCnt,srate;
  57. short atak[3][64],PawnCnt[3][8];
  58. short ChkFlag[30],CptrFlag[30],PawnThreat[30],PPscore[30];
  59. short BookSize,BookDepth;
  60. short GameCnt,Game50,epsquare,lpost;
  61. unsigned short GameList[240],Book[80][24];
  62. short GameScore[240],GamePc[240],GameClr[240];
  63. short value[8]={0,100,330,330,500,950,999};
  64. short otherside[3]={0,2,1};
  65. short passed_pawn1[8]={0,3,4,8,14,24,40,80};
  66. short passed_pawn2[8]={0,2,3,4,6,9,13,80};
  67. short passed_pawn3[8]={0,1,2,3,4,5,6,80};
  68. short map[64]=
  69.    {26,27,28,29,30,31,32,33,38,39,40,41,42,43,44,45,
  70.     50,51,52,53,54,55,56,57,62,63,64,65,66,67,68,69,
  71.     74,75,76,77,78,79,80,81,86,87,88,89,90,91,92,93,
  72.     98,99,100,101,102,103,104,105,110,111,112,113,114,115,116,117};
  73. short unmap[144]=
  74.    {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
  75.     -1,-1,0,1,2,3,4,5,6,7,-1,-1,-1,-1,8,9,10,11,12,13,14,15,-1,-1,
  76.     -1,-1,16,17,18,19,20,21,22,23,-1,-1,-1,-1,24,25,26,27,28,29,30,31,-1,-1,
  77.     -1,-1,32,33,34,35,36,37,38,39,-1,-1,-1,-1,40,41,42,43,44,45,46,47,-1,-1,
  78.     -1,-1,48,49,50,51,52,53,54,55,-1,-1,-1,-1,56,57,58,59,60,61,62,63,-1,-1,
  79.     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
  80. short edge[64]=
  81.    {0,1,2,3,3,2,1,0,1,2,3,4,4,3,2,1,2,3,4,5,5,4,3,2,3,4,5,6,6,5,4,3,
  82.     3,4,5,6,6,5,4,3,2,3,4,5,5,4,3,2,1,2,3,4,4,3,2,1,0,1,2,3,3,2,1,0};
  83. short pknight[64]=
  84.    {0,6,11,14,14,11,6,0,6,12,22,25,25,22,12,6,
  85.     11,20,30,36,36,30,20,11,14,25,36,44,44,36,25,14,
  86.     14,25,36,44,44,36,25,14,11,20,30,36,36,30,20,11,
  87.     6,12,22,25,25,22,12,6,0,6,11,14,14,11,6,0};
  88. short pbishop[64]=
  89.    {14,14,14,14,14,14,14,14,14,18,18,18,18,18,18,14,
  90.     14,18,22,22,22,22,18,14,14,18,22,22,22,22,18,14,
  91.     14,18,22,22,22,22,18,14,14,18,22,22,22,22,18,14,
  92.     14,18,18,18,18,18,18,14,14,14,14,14,14,14,14,14};
  93. short board[64]=
  94.    {rook,knight,bishop,queen,king,bishop,knight,rook,
  95.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  96.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.     pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
  98.     rook,knight,bishop,queen,king,bishop,knight,rook};
  99. short piece_color[64]=
  100.    {white,white,white,white,white,white,white,white,
  101.     white,white,white,white,white,white,white,white,
  102.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  103.     black,black,black,black,black,black,black,black,
  104.     black,black,black,black,black,black,black,black};
  105. short sweep[7]= {false,false,false,true,true,true,false};
  106. short Dstpwn[3]={0,4,6};
  107. short Dstart[7]={6,4,8,4,0,0,0};
  108. short Dstop[7]={7,5,15,7,3,7,7};
  109. short Dir[16]={1,12,-1,-12,11,13,-11,-13,10,-10,14,-14,23,-23,25,-25};
  110. unsigned short PV,Swag1,Swag2,killr1[30],killr2[30],killr3[30],Qkillr[30];
  111. unsigned short Ckillr[3],prvar[30];
  112.  
  113.  
  114. main()
  115. {
  116.   initscr();
  117.   NewGame();
  118.   while (!(quit))
  119.     {
  120.       if (bothsides && !mate) select_move(opponent); else input_command();
  121.       if (!quit && !mate) select_move(computer);
  122.     }
  123.   endwin();
  124. }
  125.  
  126.  
  127. OpeningBook(side)
  128. short side;
  129. {
  130. short i,j,r0,pnt;
  131. unsigned m,r;
  132.   srand(time(NULL));
  133.   r0 = m = 0;
  134.   for (i = 0; i < BookSize; i++)
  135.     {
  136.       for (j = 0; j <= GameCnt; j++)
  137.         if (GameList[j] != Book[i][j]) break;
  138.       if (j > GameCnt)
  139.         if ((r=rand()) > r0)
  140.           {
  141.             r0 = r; m = Book[i][GameCnt+1];
  142.           }
  143.     }
  144.   for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
  145.     if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
  146.   sort(TrPnt[1],TrPnt[2]-1);
  147.   if (Tree[TrPnt[1]].score < 0) BookDepth = -1;
  148. }
  149.  
  150.  
  151. select_move(side)
  152. short side;
  153.  
  154. /*
  155.      Select a move by calling function search() at progressively deeper
  156.      ply until time is up or a mate or draw is reached. An alpha-beta 
  157.      window of -0, +75 points is set around the score returned from the
  158.      previous iteration. 
  159. */
  160.  
  161. {
  162. short i,alpha,beta,tempb,tempc;
  163.  
  164.   timeout = false; player = side;
  165.   for (i = 0; i < 30; i++)
  166.     prvar[i] = killr1[i] = killr2[i] = killr3[i] = 0;
  167.   PPscore[0] = -5000;
  168.   alpha = -9999; beta = 9999;
  169.   NodeCnt = Sdepth = extra_time = 0;
  170.   ataks(white,atak[white]); ataks(black,atak[black]);
  171.   TrPnt[1] = 0; root = &Tree[0];
  172.   MoveList(side,1);
  173.   if (GameCnt < BookDepth) OpeningBook(side); else BookDepth = -1;
  174.   if (BookDepth > 0) timeout = true;
  175.   while (!timeout && Sdepth<30)
  176.     {
  177.       Sdepth++;
  178.       gotoXY(70,1); printw("%d ",Sdepth); ClrEoln();
  179.       search(side,1,Sdepth,alpha,beta,prvar);
  180.       if (root->score < alpha)
  181.         search(side,1,Sdepth,-12000,alpha,prvar);
  182.       if (root->score > beta && !(root->flags & exact))
  183.         {
  184.           gotoXY(70,1); printw("%d+",Sdepth); ClrEoln();
  185.           search(side,1,Sdepth,beta,12000,prvar);
  186.         }
  187.       beta = root->score+75;
  188.       if (root->flags & exact) timeout = true;
  189.     }
  190.   if (root->score > -9999)
  191.     {
  192.       MakeMove(side,root,&tempb,&tempc);
  193.       algbrnot(root->f,root->t);
  194.       PrintBoard(side,root->f,root->t,0);
  195.       gotoXY(50,16); printw("My move is: %s",mvstr1); ClrEoln();
  196.     }
  197.   ElapsedTime(1);
  198.   gotoXY(18,23); printw("Nodes= %d",NodeCnt); ClrEoln();
  199.   gotoXY(18,24); printw("Nodes/Sec= %d",srate); ClrEoln();
  200.   gotoXY(50,13);
  201.   if (root->flags & draw) printw("draw game!");
  202.   if (root->score < -9000) printw("opponent will soon mate!");
  203.   if (root->score > 9000)  printw("computer will soon mate!");
  204.   if (root->score == -9999)
  205.     {
  206.       gotoXY(50,13);
  207.       printw("opponent mates!!"); mate = true;
  208.     }
  209.   if (root->score == 9998)
  210.     {
  211.       gotoXY(50,13);
  212.       printw("computer mates!!"); mate = true;
  213.     }
  214.   ClrEoln();
  215.   if (post) post_move(root);
  216.   if (root->f == 255 || root->t == 255) Game50 = GameCnt;
  217.   else if (board[root->t] == pawn || (root->flags & capture)) 
  218.     Game50 = GameCnt;
  219.   GameScore[GameCnt] = root->score;
  220.   if (GameCnt > 238) quit = true;
  221.   player = otherside[side];
  222. }
  223.  
  224.  
  225. VerifyMove(s,ok)
  226. char s[];
  227. short *ok;
  228.  
  229. /*
  230.     See if the opponents move is legal, if so, make it.
  231. */
  232.  
  233. {
  234. short x,pnt,cnt,tempb,tempc;
  235. unsigned short nxtline[30];
  236. struct leaf *node,*xnode;
  237.  
  238.   *ok = false; cnt = 0;
  239.   MoveList(opponent,2);
  240.   pnt = TrPnt[2];
  241.   while (pnt < TrPnt[3])
  242.     {
  243.       node = &Tree[pnt]; pnt++;
  244.       algbrnot(node->f,node->t);
  245.       if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
  246.         {
  247.           xnode = node; cnt++;
  248.         }
  249.     }
  250.   if (cnt == 1)
  251.     {
  252.       MakeMove(opponent,xnode,&tempb,&tempc);
  253.       CaptureSearch(computer,opponent,3,1,-9999,9999,0,&x,nxtline);
  254.       if (x == 10000) UnmakeMove(opponent,xnode,&tempb,&tempc);
  255.       else
  256.         {
  257.           *ok = true; PrintBoard(opponent,xnode->f,xnode->t,0);
  258.           if (xnode->f == 255 || xnode->t == 255) Game50 = GameCnt;
  259.           else if (board[xnode->t] == pawn || (xnode->flags & capture)) 
  260.             Game50 = GameCnt;
  261.         } 
  262.     }
  263. }
  264.  
  265.  
  266. input_command()
  267. {
  268. short ok,i,f,t;
  269. char s[20],fname[20];
  270. FILE *fd;
  271.  
  272.   ok=quit=false;
  273.   while (!(ok || quit))
  274.     {
  275.       gotoXY(50,21); printw("Your move is? "); ClrEoln();
  276.       scanw("%s",s);
  277.       player = opponent;
  278.       VerifyMove(s,&ok);
  279.       if (strcmp(s,"prt") == 0)
  280.         {
  281.           ClrScreen();  PrintBoard(white,0,0,1);
  282.         }
  283.       if (strcmp(s,"quit") == 0) quit = true;
  284.       if (strcmp(s,"post") == 0) post = !post;
  285.       if (strcmp(s,"set") == 0) SetBoard();
  286.       if (strcmp(s,"go") == 0) ok = true;
  287.       if (strcmp(s,"help") == 0) help();
  288.       if (strcmp(s,"hint") == 0)
  289.         {
  290.           algbrnot(prvar[2]>>8,prvar[2] & 0xFF);
  291.           gotoXY(50,13); printw("try %5s",mvstr1); ClrEoln();
  292.         }
  293.       if (strcmp(s,"both") == 0)
  294.         {
  295.           bothsides = !bothsides;
  296.           select_move(opponent);
  297.           ok = true;
  298.         }
  299.       if (strcmp(s,"reverse") == 0)
  300.         {
  301.           reverse = !reverse;
  302.           ClrScreen();
  303.           PrintBoard(white,0,0,1);
  304.         }
  305.       if (strcmp(s,"switch") == 0)
  306.         {
  307.           computer = otherside[computer];
  308.           opponent = otherside[opponent];
  309.           ok = true;
  310.         }
  311.       if (strcmp(s,"save") == 0)
  312.         {
  313.           gotoXY(50,21); ClrEoln();
  314.           printw("file name? "); scanw("%s",fname);
  315.           SaveGame(fname);
  316.         }
  317.       if (strcmp(s,"get") == 0)
  318.         {
  319.           gotoXY(50,21); ClrEoln();
  320.           printw("file name? "); scanw("%s",fname);
  321.           GetGame(fname);
  322.           InitializeStats();
  323.           PrintBoard(white,0,0,1);
  324.         }
  325.       if (strcmp(s,"time") == 0)
  326.         {
  327.           gotoXY(50,21); printw("enter time: "); ClrEoln();
  328.           scanw("%d",&response_time);
  329.         }
  330.       if (strcmp(s,"undo") == 0 && GameCnt > 0)
  331.         {
  332.           f = GameList[GameCnt]>>8; t = GameList[GameCnt] & 0xFF;
  333.           board[f] = board[t]; piece_color[f] = piece_color[t];
  334.           board[t] = GamePc[GameCnt]; piece_color[t] = GameClr[GameCnt];
  335.           GameCnt--;
  336.           PrintBoard(white,0,0,1);
  337.           InitializeStats();
  338.         }
  339.       if (strcmp(s,"list") == 0)
  340.         {
  341.           fd = fopen("chess.lst","w");
  342.           for (i = 0; i <= GameCnt; i++)
  343.             {
  344.               f = GameList[i]>>8; t = (GameList[i] & 0xFF);
  345.               algbrnot(f,t);
  346.               if ((i % 2) == 0) fprintf(fd,"\n");
  347.               fprintf(fd," %5s  %6d     ",mvstr1,GameScore[i]);
  348.             }
  349.           fprintf(fd,"\n");
  350.           fclose(fd);
  351.         }
  352.     }
  353.   ElapsedTime(1);
  354. }
  355.  
  356.  
  357. gotoXY(x,y)
  358. short x,y;
  359. {
  360.   move(y-1,x-1);
  361. }
  362.  
  363.  
  364. ClrScreen()
  365. {
  366.   clear(); refresh();
  367. }
  368.  
  369.  
  370. ClrEoln()
  371. {
  372.   clrtoeol(); refresh();
  373. }
  374.  
  375.  
  376. algbrnot(f,t)
  377. short f,t;
  378. {
  379.   if (f == 255)
  380.     { strcpy(mvstr1,"o-o"); strcpy(mvstr2,"o-o"); }
  381.   else if (t == 255)
  382.     { strcpy(mvstr1,"o-o-o"); strcpy(mvstr2,"o-o"); }
  383.   else
  384.     {
  385.       mvstr1[0] = cx[col[f]]; mvstr1[1] = rx[row[f]];
  386.       mvstr1[2] = cx[col[t]]; mvstr1[3] = rx[row[t]];
  387.       mvstr2[0] = qx[board[f]];
  388.       mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
  389.       mvstr1[4] = '\0'; mvstr2[3] = '\0';
  390.     }
  391. }
  392.  
  393.  
  394. parse(s,m)
  395. unsigned short *m; char s[];
  396. {
  397. short r1,r2,c1,c2;
  398.   if (s[4] == 'o') *m = 0x00FF;
  399.   else if (s[0] == 'o') *m = 0xFF00;
  400.   else
  401.     {
  402.       c1 = s[0] - 'a'; r1 = s[1] - '1';
  403.       c2 = s[2] - 'a'; r2 = s[3] - '1';
  404.       *m = (locn[r1][c1]<<8) + locn[r2][c2];
  405.     }
  406. }
  407.  
  408.  
  409. GetOpenings()
  410. {
  411. FILE *fd;
  412. int c,j;
  413. char s[80],*p;
  414.   fd = fopen("chess.opn","r");
  415.   BookSize = 0; BookDepth = 24; j = -1; c = '?';
  416.   while (c != EOF)
  417.     {
  418.       p = s;
  419.       while ((c=getc(fd)) != EOF)
  420.         if (c == '\n') break; else *(p++) = c;
  421.       *p = '\0';
  422.       if (c != EOF)
  423.         if (s[0] == '!')
  424.           {
  425.             while (j < BookDepth) Book[BookSize][j++] = 0; 
  426.             BookSize++; j = -1;
  427.           }
  428.         else if (j < 0) j++;
  429.         else
  430.           {
  431.             parse(&s[0],&Book[BookSize][j]); j++;
  432.             parse(&s[6],&Book[BookSize][j]); j++;
  433.           } 
  434.     }
  435.   fclose(fd);
  436. }
  437.  
  438.  
  439. GetGame(fname)
  440. char fname[20];
  441. {
  442. FILE *fd;
  443. int c;
  444. short loc;
  445. unsigned short m;
  446.  
  447.   if (fname[0] == '\0') strcpy(fname,"chess.000");
  448.   if ((fd = fopen(fname,"r")) != NULL)
  449.     {
  450.       fscanf(fd,"%hd%hd",&castld[white],&castld[black]);
  451.       fscanf(fd,"%hd%hd",&kingmoved[white],&kingmoved[black]);
  452.       for (loc = 0; loc < 64; loc++)
  453.         {
  454.           fscanf(fd,"%hd",&m); board[loc] = (m >> 8); piece_color[loc] = (m & 0xFF);
  455.         }
  456.       GameCnt = -1; c = '?';
  457.       while (c != EOF)
  458.         c = fscanf(fd,"%hd%hd%hd%hd",&GameList[++GameCnt],&GameScore[GameCnt],
  459.                    &GamePc[GameCnt],&GameClr[GameCnt]);
  460.     }
  461.   fclose(fd);
  462. }
  463.  
  464.  
  465. SaveGame(fname)
  466. char fname[20];
  467. {
  468. FILE *fd;
  469. short loc,i;
  470.  
  471.   if (fname[0] == '\0') strcpy(fname,"chess.000");
  472.   fd = fopen(fname,"w");
  473.   fprintf(fd,"%d %d\n",castld[white],castld[black]);
  474.   fprintf(fd,"%d %d\n",kingmoved[white],kingmoved[black]);
  475.   for (loc = 0; loc < 64; loc++)
  476.     fprintf(fd,"%d\n",256*board[loc] + piece_color[loc]);
  477.   for (i = 0; i <= GameCnt; i++)
  478.     fprintf(fd,"%d %d %d %d\n",GameList[i],GameScore[i],GamePc[i],GameClr[i]);
  479.   fclose(fd);
  480. }
  481.  
  482.  
  483. ElapsedTime(iop)
  484. short iop;
  485. {
  486. int minute,second;
  487.   et = time(NULL) - time0;
  488.   if (et < et0) et0 = 0;
  489.   if (et > et0 || iop == 1)
  490.     {
  491.       if (et > response_time+extra_time) timeout = true;
  492.       et0 = et;
  493.       if (iop == 1)
  494.         {
  495.           et0 = 0; time0 = time(NULL);
  496.         }
  497.       minute = et/60; second = (et - 60*minute);
  498.       if (player == computer) gotoXY(50,18); else gotoXY(50,23);
  499.       printw("%d:%02d",minute,second); ClrEoln();
  500.       if (et > 0) srate = NodeCnt/et; else srate = 0;
  501.       if (post)
  502.         {
  503.           gotoXY(18,24); printw("Nodes/Sec= %d",srate); ClrEoln();
  504.         }
  505.     }
  506. }
  507.  
  508.  
  509. post_move(node)
  510. struct leaf *node;
  511. {
  512. short d,e,ply;
  513.   d = 4; ply = 1;
  514.   gotoXY(60,d); printw("%6d  ",node->score);
  515.   while (prvar[ply] > 0)
  516.     {
  517.       algbrnot(prvar[ply]>>8,prvar[ply] & 0x00FF);
  518.       gotoXY(50,d); printw("%5s",mvstr1);
  519.       ply++; d++;
  520.     }
  521.   e = d;
  522.   while (d < lpost)
  523.     {
  524.       gotoXY(50,d++); ClrEoln();
  525.     }
  526.   lpost = e;
  527.   refresh();
  528. }
  529.  
  530.  
  531. DrawPiece(loc)
  532. short loc;
  533. {
  534. short r,c; char x;
  535.   if (reverse) r = 7-row[loc]; else r = row[loc];
  536.   if (reverse) c = 7-col[loc]; else c = col[loc];
  537.   if (piece_color[loc] == black) x = '*'; else x = ' ';
  538.   gotoXY(5+5*c,4+2*(7-r)); printw("%c%c",x,px[board[loc]]," ");
  539. }
  540.  
  541.  
  542. PrintBoard(side,f,t,flag)
  543. short side,f,t,flag;
  544. {
  545. short i,l,c,z; 
  546.  
  547.   if (side == white) c = 0; else c = 56;
  548.   if (flag)
  549.     {
  550.       i = 2;
  551.       gotoXY(3,++i);
  552.       printw("|----|----|----|----|----|----|----|----|");
  553.       while (i<19)
  554.         {
  555.           gotoXY(1,++i);
  556.           if (reverse) z = (i/2)-1; else z = 10-(i/2);
  557.           printw("%d |    |    |    |    |    |    |    |    |",z);
  558.           gotoXY(3,++i);
  559.           printw("|----|----|----|----|----|----|----|----|");
  560.         }
  561.       gotoXY(3,20);
  562.       if (reverse) printw("   h    g    f    e    d    c    b    a");
  563.               else printw("   a    b    c    d    e    f    g    h");
  564.       for (l = 0; l < 64; l++) DrawPiece(l);
  565.     }
  566.   else if (f == 255)
  567.     {
  568.       DrawPiece(c+4); DrawPiece(c+6);
  569.       DrawPiece(c+7); DrawPiece(c+5);
  570.     }
  571.   else if (t == 255)
  572.     {
  573.       DrawPiece(c+4); DrawPiece(c+2);
  574.       DrawPiece(c); DrawPiece(c+3);
  575.     }
  576.   else
  577.     {
  578.       DrawPiece(f); DrawPiece(t);
  579.     }
  580.   refresh();
  581. }
  582.  
  583.  
  584. SetBoard()
  585. {
  586. short a,r,c,loc;
  587. char s[20];
  588.  
  589.   ClrScreen(); PrintBoard(white,0,0,1);
  590.   a = white;
  591.   do
  592.   {
  593.     gotoXY(50,2); printw(".    Exit to Main");
  594.     gotoXY(50,3); printw("#    Clear Board");
  595.     gotoXY(49,5);
  596.     printw("Enter piece & location: "); ClrEoln(); scanw("%s",s);
  597.     if (s[0] == '#')
  598.       {
  599.         for (loc = 0; loc < 64; loc++)
  600.           { board[loc] = no_piece; piece_color[loc] = neutral; }
  601.         PrintBoard(white,0,0,1);
  602.       }
  603.     if (s[0] == 'c' || s[0] == 'C') a = otherside[a];
  604.     c = s[1]-'a'; r = s[2]-'1';
  605.     if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  606.       {
  607.         loc = locn[r][c];
  608.         piece_color[loc] = a;
  609.         if (s[0] == 'p') board[loc] = pawn;
  610.         else if (s[0] == 'n') board[loc] = knight;
  611.         else if (s[0] == 'b') board[loc] = bishop;
  612.         else if (s[0] == 'r') board[loc] = rook;
  613.         else if (s[0] == 'q') board[loc] = queen;
  614.         else if (s[0] == 'k') board[loc] = king;
  615.         else { board[loc] = no_piece; piece_color[loc] = neutral; }
  616.         DrawPiece(loc); refresh();
  617.       }
  618.   }
  619.   while (s[0] != '.');
  620.   if (board[4] != king) kingmoved[white] = 10;
  621.   if (board[61] != king) kingmoved[black] = 10;
  622.   GameCnt = -1; Game50 = -1; BookDepth = 0;
  623.   InitializeStats(); ClrScreen(); PrintBoard(white,0,0,1);
  624. }
  625.   
  626.  
  627. NewGame()
  628. {
  629. short l,r,c;
  630.  
  631.   mate = quit = reverse = bothsides = post = false;
  632.   lpost =  NodeCnt = epsquare = xkillr = 0;
  633.   GameCnt = Game50 = -1;
  634.   castld[white] = castld[black] = false;
  635.   kingmoved[white] = kingmoved[black] = 0;
  636.   opponent = white; computer = black;
  637.   for (r = 0; r < 8; r++)
  638.     for (c = 0; c < 8; c++)
  639.       {
  640.         l = 8*r+c; locn[r][c] = l;
  641.         row[l] = r; col[l] = c;
  642.       }
  643.   ClrScreen(); gotoXY(1,20);
  644.   printw("enter response time: "); ClrEoln();
  645.   scanw("%d",&response_time);
  646.   ClrScreen(); PrintBoard(white,0,0,1);
  647.   
  648.   InitializeStats();
  649.   ElapsedTime(1);
  650.   GetOpenings();
  651. }
  652.  
  653.  
  654. help()
  655. {
  656. char c;
  657.  
  658. ClrScreen();
  659. printw("\n");
  660. printw("This program attempts to play CHESS\n\n");
  661. printw("To make a move, enter the column (labelled 'a' - 'h') and\n");
  662. printw("row (labelled '1' - '8') of the 'from' and 'to' squares.\n");
  663. printw("For example, to move the kings pawn forward 2 squares, type e2e4.\n");
  664. printw("Other commands are:\n\n");
  665. printw("o-o           castle king side\n");
  666. printw("o-o-o         castle queen side\n");
  667. printw("set           set up a board position\n");
  668. printw("switch        switch sides with computer\n");
  669. printw("go            skip your move\n");
  670. printw("reverse       reverse board display\n");
  671. printw("both          computer plays both sides\n");
  672. printw("time          change response time\n");
  673. printw("post          post best line of play\n");
  674. printw("hint          computer suggests your move\n");
  675. printw("list          list moves to file chess.lst\n");
  676. printw("save          save game to disk\n");
  677. printw("get           get game from disk\n");
  678. printw("quit          exit CHESS\n");
  679. refresh();
  680. #ifdef AMIGA
  681. ttgetc();
  682. #else
  683. while ((c=getchar()) != '\n');
  684. scanw("%c",&c);
  685. #endif
  686. ClrScreen();
  687. PrintBoard(white,0,0,1);
  688. }
  689.  
  690.  
  691. UpdatePieceList(side,loc,iop)
  692. short side,loc,iop;
  693.  
  694. /*
  695.     Array PieceList[side][indx] contains the location of all the pieces of
  696.     either side. Array indx[loc] contains the indx into PieceList for a
  697.     given square.
  698. */
  699.  
  700. {
  701. register short i;
  702.   if (iop == 1)
  703.     {
  704.       PieceCnt[side]--;
  705.       for (i = indx[loc]; i <= PieceCnt[side]; i++)
  706.         {
  707.           PieceList[side][i] = PieceList[side][i+1];
  708.           indx[PieceList[side][i]] = i;
  709.         }
  710.     }
  711.   else
  712.     {
  713.       PieceCnt[side]++;
  714.       PieceList[side][PieceCnt[side]] = loc;
  715.       indx[loc] = PieceCnt[side];
  716.     }
  717. }
  718.  
  719.  
  720. InitializeStats()
  721. {
  722. register short i,loc;
  723.   for (i = 0; i < 8; i++)
  724.     PawnCnt[white][i] = PawnCnt[black][i] = 0;
  725.   mtl[white] = mtl[black] = pmtl[white] = pmtl[black]=0;
  726.   PieceCnt[white] = PieceCnt[black] = 0;
  727.   for (loc = 0; loc < 64; loc++)
  728.     if (piece_color[loc] != neutral)
  729.       {
  730.         mtl[piece_color[loc]] += value[board[loc]];
  731.         if (board[loc] == pawn)
  732.           {
  733.             pmtl[piece_color[loc]] += value[pawn];
  734.             ++PawnCnt[piece_color[loc]][col[loc]];
  735.           }
  736.         if (board[loc] == king) indx[loc] = 0;
  737.           else indx[loc] = ++PieceCnt[piece_color[loc]];
  738.         PieceList[piece_color[loc]][indx[loc]] = loc;
  739.       }
  740. }
  741.  
  742.  
  743. sort(p1,p2)
  744. short p1,p2;
  745. {
  746. register short p,p0,s;
  747. struct leaf temp;
  748.  
  749.   s = 32000;
  750.   while (p1 < p2)
  751.     if (Tree[p1].score >= s) p1++;
  752.     else
  753.       {
  754.         s = Tree[p1].score; p0 = p1;
  755.         for (p = p1+1; p <= p2; p++)
  756.           if (Tree[p].score > s)
  757.             {
  758.               s = Tree[p].score; p0 = p;
  759.             }
  760.         temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
  761.         p1++;
  762.       }
  763. }
  764.  
  765.  
  766. repetition(node)
  767. struct leaf *node;
  768. /*
  769.     Check for draw by threefold repetition or 50 move rule.
  770. */
  771. {
  772. register short i,f,t,c;
  773. short r,b[64];
  774. unsigned short m;
  775.   r = c = 0;
  776. #ifdef AMIGA
  777.   setmem(b, 64*sizeof(short), 0);
  778. #else
  779.   memset(b,0,64*sizeof(short));
  780. #endif
  781.   for (i = GameCnt; i > Game50; i--)
  782.     {
  783.       m = GameList[i]; f = m>>8; t = m & 0xFF;
  784.       if (t != 255 && f != 255)
  785.         {
  786.           b[f]++; b[t]--;
  787.           if (b[f] == 0) c--; else c++;
  788.           if (b[t] == 0) c--; else c++;
  789.           if (c == 0) r++;
  790.         }
  791.     }
  792.   if (r == 1)
  793.     if (node->score > 0) node->score -= 20;
  794.     else node->score += 20;
  795.   if (GameCnt-Game50 > 99 || r == 2)
  796.     {
  797.       node->score = 0;
  798.       node->flags |= exact;
  799.       node->flags |= draw;
  800.     }
  801. }
  802.  
  803.  
  804. ataks(side,a)
  805. short side,a[];
  806.  
  807. /*
  808.     Place the lowest value piece attacking a square into array atak[][].
  809. */
  810.  
  811. {
  812. register short m,u,d,j;
  813. short piece,i,m0,*aloc,*s;
  814.  
  815. #ifdef AMIGA
  816.   setmem(a, 64*sizeof(short),0);
  817. #else 
  818.   a = (short *)memset(a,0,64*sizeof(short));
  819. #endif
  820.   Dstart[pawn] = Dstpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  821.   aloc = &PieceList[side][0];
  822.   for (i = 0; i <= PieceCnt[side]; i++)
  823.     {
  824.       piece = board[*aloc]; m0 = map[*aloc];
  825.       s = &svalue[*aloc]; *s = 0;
  826.       aloc++;
  827.       if (sweep[piece])
  828.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  829.           {
  830.             d = Dir[j]; m = m0+d; u = unmap[m];
  831.             while (u >= 0)
  832.               {
  833.                 *s += 2;
  834.                 if (a[u] == 0 || piece < a[u]) a[u] = piece;
  835.                 if (piece_color[u] == neutral)
  836.                   {
  837.                     m += d; u = unmap[m];
  838.                   }
  839.                 else u = -1;
  840.               }
  841.           }
  842.       else
  843.         {
  844.           for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  845.             if ((u = unmap[m0+Dir[j]]) >= 0)
  846.               if (a[u] == 0 || piece < a[u]) a[u] = piece;
  847.         }
  848.     }
  849. }
  850.  
  851.   
  852. castle(side,f,t,iop,ok)
  853. short side,f,t,iop,*ok;
  854. {
  855. short i,e,k1,k2,r1,r2,c1,c2,t0,xside;
  856.  
  857.   xside = otherside[side];
  858.   if (side == white) e = 0; else e = 56;
  859.   if (f == 255)
  860.     {
  861.       k1 = e+4; k2 = e+6; r1 = e+7; r2 = e+5; c1 = k1; c2 = r1;
  862.     }
  863.   else
  864.     {
  865.       k1 = e+4; k2 = e+2; r1 = e; r2 = e+3; c1 = r1; c2 = k1;
  866.     }
  867.   if (iop == 0)
  868.     {
  869.       *ok = false;
  870.       if (board[k1] == king && board[r1] == rook) *ok = true;
  871.       for (i = c1; i <= c2; i++)
  872.         if (atak[xside][i] > 0) *ok = false; 
  873.       for (i = c1+1; i < c2; i++)
  874.         if (piece_color[i] != neutral) *ok = false;
  875.     }
  876.   else
  877.     {
  878.       if (iop == 1) castld[side] = true; else castld[side] = false;
  879.       if (iop == 2)
  880.         {
  881.           t0 = k1; k1 = k2; k2 = t0;
  882.           t0 = r1; r1 = r2; r2 = t0;
  883.         }
  884.       board[k2] = king; piece_color[k2] = side; indx[k2] = 0;
  885.       board[k1] = no_piece; piece_color[k1] = neutral;
  886.       board[r2] = rook; piece_color[r2] = side; indx[r2] = indx[r1];
  887.       board[r1] = no_piece; piece_color[r1] = neutral;
  888.       PieceList[side][indx[k2]] = k2;
  889.       PieceList[side][indx[r2]] = r2;
  890.     }
  891. }
  892.  
  893.  
  894. en_passant(side,xside,f,t,iop)
  895. short side,f,t,iop;
  896. {
  897. short l;
  898.   if (t > f) l = t-8; else l = t+8;
  899.   if (iop == 1)
  900.     {
  901.       board[l] = no_piece; piece_color[l] = neutral;
  902.     }
  903.   else 
  904.     {
  905.       board[l] = pawn; piece_color[l] = xside;
  906.     }
  907.   InitializeStats();
  908. }
  909.  
  910.  
  911. LinkMove(ply,f,t,side,xside)
  912. short ply,f,t,side,xside;
  913. {
  914.  
  915. /*
  916.     Add a move to the tree.  Assign a bonus (in an attempt to
  917.     improve move ordering) if move is a
  918.     principle variation, "killer", or capturing move.
  919. */
  920.  
  921. register short s;
  922. unsigned short mv;
  923. struct leaf *node;
  924.  
  925.   node = &Tree[TrPnt[ply+1]];
  926.   ++TrPnt[ply+1];
  927.   node->flags = node->reply = 0;
  928.   node->f = f; node->t = t; mv = (f<<8) + t;
  929.   if (f == 255 || t == 255) s = 100;
  930.   else
  931.     {
  932.       s = 0;
  933.       if (mv == PV) s = 150;
  934.       else if (mv == killr1[ply]) s = 90;
  935.       else if (mv == killr2[ply]) s = 70;
  936.       else if (mv == killr3[ply]) s = 50;
  937.       else if (mv == Swag1) s = 30;
  938.       else if (mv == Swag2) s = 20;
  939.       if (piece_color[t] != neutral)
  940.         {
  941.           node->flags |= capture;
  942.           if (t == xkillr) s += 400;
  943.           if (atak[xside][t] == 0) s += value[board[t]]-board[f];
  944.           else if (board[t] > board[f]) s += value[board[t]]-value[board[f]];
  945.           else s += 15;
  946.         }
  947.       if (board[f] == pawn)
  948.         {
  949.           if (row[t] == 0 || row[t] == 7) node->flags |= promote;
  950.           else if (row[t] == 1 || row[t] == 6) node->flags |= pwnthrt;
  951.           else if (t == epsquare) node->flags |= epmask;
  952.         }
  953.       if (atak[xside][f] > 0) s += 15;
  954.       if (atak[xside][t] > 0) s -= 20;
  955.       if (InChk)
  956.         {
  957.           if (board[f] == king && atak[xside][t] == 0) s += 600;  
  958.           if (mv == Qkillr[ply]) s += 100;
  959.         }
  960.     }
  961.   node->score = s-20000;
  962. }
  963.  
  964.  
  965. GenMoves(ply,loc,side,xside)
  966. short ply,loc,side,xside;
  967.  
  968. /*
  969.      Generate moves for a piece. The from square is mapped onto a 12 by 
  970.      12 board and offsets (taken from array Dir[]) are added to the 
  971.      mapped location. Array unmap[] maps the move back onto array 
  972.      board[] (yielding a value of -1 if the to square is off the board). 
  973.      This process is repeated for bishops, rooks, and queens until a 
  974.      piece is encountered or the the move falls off the board. Legal 
  975.      moves are then linked into the tree. 
  976. */
  977.     
  978. {
  979. register short m,u,d;
  980. short i,m0,piece; 
  981.  
  982.   piece = board[loc]; m0 = map[loc];
  983.   if (sweep[piece])
  984.     {
  985.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  986.         {
  987.           d = Dir[i]; m = m0+d; u = unmap[m];
  988.           while (u >= 0)
  989.             if (piece_color[u] == neutral)
  990.               {
  991.                 LinkMove(ply,loc,u,side,xside);
  992.                 m += d; u = unmap[m];
  993.               }
  994.             else if (piece_color[u] == xside)
  995.               {
  996.                 LinkMove(ply,loc,u,side,xside);
  997.                 u = -1;
  998.               }
  999.             else u = -1;
  1000.         }
  1001.     }
  1002.   else if (piece == pawn)
  1003.     {
  1004.       if (side == white && piece_color[loc+8] == neutral)
  1005.         {
  1006.           LinkMove(ply,loc,loc+8,side,xside);
  1007.           if (row[loc] == 1)
  1008.             if (piece_color[loc+16] == neutral)
  1009.               LinkMove(ply,loc,loc+16,side,xside);
  1010.         }
  1011.       else if (side == black && piece_color[loc-8] == neutral)
  1012.         {
  1013.           LinkMove(ply,loc,loc-8,side,xside);
  1014.           if (row[loc] == 6)
  1015.             if (piece_color[loc-16] == neutral)
  1016.               LinkMove(ply,loc,loc-16,side,xside);
  1017.         }
  1018.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  1019.         if ((u = unmap[m0+Dir[i]]) >= 0)
  1020.           if (piece_color[u] == xside || u == epsquare)
  1021.             LinkMove(ply,loc,u,side,xside);
  1022.     }
  1023.   else
  1024.     {
  1025.       for (i = Dstart[piece]; i <= Dstop[piece]; i++)
  1026.         if ((u = unmap[m0+Dir[i]]) >= 0)
  1027.           if (piece_color[u] != side)
  1028.             LinkMove(ply,loc,u,side,xside);
  1029.     }
  1030. }
  1031.  
  1032.  
  1033.  
  1034. MoveList(side,ply)
  1035. short side,ply;
  1036.  
  1037. /*
  1038.     Fill the array Tree[] with all available moves for side to
  1039.     play. Array TrPnt[ply] contains the index into Tree[]
  1040.     of the first move at a ply.
  1041. */
  1042.     
  1043. {
  1044. register short i;
  1045. short ok,xside;
  1046.  
  1047.   xside = otherside[side];
  1048.   TrPnt[ply+1] = TrPnt[ply];
  1049.   Dstart[pawn] = Dstpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  1050.   for (i = 0; i <= PieceCnt[side]; i++)
  1051.     GenMoves(ply,PieceList[side][i],side,xside);
  1052.   if (kingmoved[side] == 0)
  1053.     {
  1054.       castle(side,255,0,0,&ok);
  1055.       if (ok) LinkMove(ply,255,0,side,xside);
  1056.       castle(side,0,255,0,&ok);
  1057.       if (ok) LinkMove(ply,0,255,side,xside);
  1058.     }
  1059.   sort(TrPnt[ply],TrPnt[ply+1]-1);
  1060. }
  1061.  
  1062.  
  1063. MakeMove(side,node,tempb,tempc)
  1064. short side,*tempc,*tempb;
  1065. struct leaf *node;
  1066.  
  1067. /*
  1068.     Update Arrays board[], piece_color[], and indx[] to reflect the new
  1069.     board position obtained after making the move pointed to by
  1070.     node.  Also update miscellaneous stuff that changes when a move
  1071.     is made.
  1072. */
  1073.     
  1074. {
  1075. register short f,t;
  1076. short ok,xside;
  1077.  
  1078.   xside = otherside[side];
  1079.   f = node->f; t = node->t; epsquare = -1; xkillr = t;
  1080.   GameList[++GameCnt] = (f<<8) + t;
  1081.   if (f == 255 || t == 255)
  1082.     {
  1083.       GamePc[GameCnt] = no_piece; GameClr[GameCnt] = neutral;
  1084.       castle(side,f,t,1,&ok);
  1085.     }
  1086.   else
  1087.     {
  1088.       *tempc = piece_color[t]; *tempb = board[t];
  1089.       GamePc[GameCnt] = *tempb; GameClr[GameCnt] = *tempc;
  1090.       if (*tempc != neutral)
  1091.         {
  1092.           UpdatePieceList(*tempc,t,1);
  1093.           if (*tempb == pawn) --PawnCnt[*tempc][col[t]];
  1094.           if (board[f] == pawn)
  1095.             {
  1096.               --PawnCnt[side][col[f]];
  1097.               ++PawnCnt[side][col[t]];
  1098.             }
  1099.           mtl[xside] -= value[*tempb];
  1100.           if (*tempb == pawn) pmtl[xside] -= value[pawn];
  1101.         }
  1102.       piece_color[t] = piece_color[f]; board[t] = board[f];
  1103.       indx[t] = indx[f]; PieceList[side][indx[t]] = t;
  1104.       piece_color[f] = neutral; board[f] = no_piece;
  1105.       if (board[t] == pawn)
  1106.         if (t-f == 16) epsquare = f+8;
  1107.         else if (f-t == 16) epsquare = f-8;
  1108.       if (node->flags & promote)
  1109.         {
  1110.           board[t] = queen;
  1111.           mtl[side] += value[queen] - value[pawn];
  1112.           pmtl[side] -= value[pawn];
  1113.         } 
  1114.       if (board[t] == king) ++kingmoved[side];
  1115.       if (node->flags & epmask) en_passant(side,xside,f,t,1);
  1116.     }
  1117. }
  1118.  
  1119.  
  1120. UnmakeMove(side,node,tempb,tempc)
  1121. short side,*tempc,*tempb;
  1122. struct leaf *node;
  1123.  
  1124. /*
  1125.     Take back the move pointed to by node.
  1126. */
  1127.  
  1128. {
  1129. register short f,t;
  1130. short ok,xside;
  1131.  
  1132.   xside = otherside[side];
  1133.   f = node->f; t = node->t; epsquare = -1;
  1134.   GameCnt--;
  1135.   if (f == 255 || t == 255) castle(side,f,t,2,&ok);
  1136.   else
  1137.     {
  1138.       piece_color[f] = piece_color[t]; board[f] = board[t];
  1139.       indx[f] = indx[t]; PieceList[side][indx[f]] = f;
  1140.       piece_color[t] = *tempc; board[t] = *tempb;
  1141.       if (*tempc != neutral)
  1142.         {
  1143.           UpdatePieceList(*tempc,t,2);
  1144.           if (*tempb == pawn) ++PawnCnt[*tempc][col[t]];
  1145.           if (board[f] == pawn)
  1146.             {
  1147.               --PawnCnt[side][col[t]];
  1148.               ++PawnCnt[side][col[f]];
  1149.             }
  1150.           mtl[xside] += value[*tempb];
  1151.           if (*tempb == pawn) pmtl[xside] += value[pawn];
  1152.         }
  1153.       if (node->flags & promote)
  1154.         {
  1155.           board[f] = pawn;
  1156.           mtl[side] += value[pawn] - value[queen];
  1157.           pmtl[side] += value[pawn];
  1158.         } 
  1159.       if (board[f] == king) --kingmoved[side];
  1160.       if (node->flags & epmask) en_passant(side,xside,f,t,2);
  1161.     }
  1162. }
  1163.  
  1164.  
  1165. LinkCapture(ply,f,t,ck)
  1166. short ply,f,t,ck;
  1167. {
  1168. struct leaf *node;
  1169.  
  1170.   node = &Tree[TrPnt[ply+1]];
  1171.   ++TrPnt[ply+1];
  1172.   node->flags = node->reply = 0;
  1173.   node->f = f; node->t = t;
  1174.   if (t == ykillr || t == ck) node->score = value[board[t]]-board[f];
  1175.   else node->score = value[board[t]]-value[board[f]];
  1176. }
  1177.  
  1178.  
  1179. CaptureList(side,xside,ply)
  1180. short side,xside,ply;
  1181.  
  1182. /*
  1183.     Generate a list of captures similiarly to GenMoves.
  1184. */
  1185.  
  1186. {
  1187. register short m,u,d;
  1188. short i,j,m0,piece,ck,*aloc;
  1189.  
  1190.   ck = Ckillr[side] & 0x00FF;
  1191.   TrPnt[ply+1] = TrPnt[ply];
  1192.   Dstart[pawn] = Dstpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
  1193.   aloc = &PieceList[side][0];
  1194.   for (i = 0; i <= PieceCnt[side]; i++)
  1195.     { 
  1196.       piece = board[*aloc]; m0 = map[*aloc];
  1197.       if (sweep[piece])
  1198.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  1199.           {
  1200.             d = Dir[j]; m = m0+d; u = unmap[m];
  1201.             while (u >= 0)
  1202.               if (piece_color[u] == neutral)
  1203.                 {
  1204.                   m += d; u = unmap[m];
  1205.                 }
  1206.               else
  1207.                 {
  1208.                   if (piece_color[u] == xside) LinkCapture(ply,*aloc,u,ck);
  1209.                   u = -1;
  1210.                 }
  1211.           }
  1212.       else
  1213.         for (j = Dstart[piece]; j <= Dstop[piece]; j++)
  1214.           if ((u = unmap[m0+Dir[j]]) >= 0)
  1215.             if (piece_color[u] == xside) LinkCapture(ply,*aloc,u,ck);
  1216.       aloc++;
  1217.     }
  1218.   sort(TrPnt[ply],TrPnt[ply+1]-1);
  1219. }
  1220.  
  1221.  
  1222. distance(a,b)
  1223. short a,b;
  1224. {
  1225. short d1,d2;
  1226.  
  1227.   d1 = col[a]-col[b]; if (d1 < 0) d1 = -d1;
  1228.   d2 = row[a]-row[b]; if (d2 < 0) d2 = -d2;
  1229.   if (d1 > d2) return(d1); else return(d2);
  1230. }
  1231.  
  1232.  
  1233. ScorePosition(side,score)
  1234. short side,*score;
  1235.  
  1236. /*
  1237.   Calculate a positional score for each piece as follows:
  1238.     pawns:
  1239.       material value     : 100 pts
  1240.       d,e file, not moved: -10 pts
  1241.            & also blocked: -10 pts
  1242.       doubled            : -12 pts (each pawn)
  1243.       isolated           : -24 pts
  1244.       backward           : -8  pts
  1245.          & attacked      : -6  pts
  1246.       passed             : depends on rank, material balance,
  1247.                            position of opponents king, blocked
  1248.     knights:
  1249.       material value     : 330 pts
  1250.       centre proximity   : array pknight 
  1251.     bishops:
  1252.       material value     : 330 pts
  1253.       discourage edges   : array pbishop
  1254.       mobility           : +2 pts per move  
  1255.     rooks:
  1256.       material value     : 500 pts
  1257.       mobility           : +2 pts per move
  1258.       open file          : +12 pts
  1259.       half open          : +6 pts
  1260.     queen:
  1261.       material value     : 950 pts
  1262.     king:
  1263.       castled            : ~ +10 pts (depends on material)
  1264.       king moved         : ~ -15 pts (depends on material)
  1265.       adjacent pawn      : +5 pts before endgame
  1266.       attacks to         : -5 pts each if more than 1 attack
  1267.       adjacent square        before endgame
  1268.       pawn missing from  : -10 pts before endgame
  1269.       adjacent column
  1270.       centre proximity   : -2 pts before endgame, during endgame
  1271.                            switches to a bonus for center proximity
  1272.                            dependent on opponents control of adjacent
  1273.                            squares
  1274.                            
  1275.     "hung" pieces        : -8  (1 hung piece)
  1276.                            -24 (more than 1)
  1277. */
  1278.  
  1279. {
  1280. register short i,j,a;
  1281. short loc,e,m0,u,piece,wking,bking,cwking,cbking;
  1282. short r,db,dw,s,stage1,stage2,c1,c2,a1,a2;
  1283. short pscore[3],xside,rank,column,in_square;
  1284.  
  1285.   xside = otherside[side];
  1286.   pscore[white] = pscore[black] = 0;
  1287.   emtl[white] = mtl[white] - pmtl[white] - value[king];
  1288.   emtl[black] = mtl[black] - pmtl[black] - value[king];
  1289.   wking = PieceList[white][0]; bking = PieceList[black][0];
  1290.   cwking = col[wking]; cbking = col[bking];
  1291.   stage1 = 10 - (emtl[white]+emtl[black]) / 670;
  1292.   stage2 = (stage1*stage1) / 10;
  1293.  
  1294.   for (c1 = white; c1 <= black; c1++)
  1295.   {
  1296.     c2 = otherside[c1];
  1297.     for (i = 0; i <= PieceCnt[c1]; i++)
  1298.       {
  1299.         loc = PieceList[c1][i]; piece = board[loc];
  1300.         a1 = atak[c1][loc]; a2 = atak[c2][loc];
  1301.         rank = row[loc]; column = col[loc];
  1302.         s = svalue[loc];
  1303.  
  1304.         if (piece == pawn && c1 == white)
  1305.           {
  1306.             if (column == 3 || column == 4)
  1307.               if (rank == 1)
  1308.                 {
  1309.                   s -= 10;
  1310.                   if (piece_color[loc+8] == white) s -=10;
  1311.                 }
  1312.               else if (rank == 4 && a1 == pawn) s += 8;
  1313.             if (column-cwking > 1 || cwking-column > 1) s += stage1*rank;
  1314.             if (PawnCnt[white][column] > 1) s -= 12;
  1315.             if (column > 0 && PawnCnt[white][column-1] == 0 &&
  1316.                 column < 7 && PawnCnt[white][column+1] == 0) s -= 24;
  1317.             if (a1 != pawn && atak[c1][loc+8] != pawn)
  1318.               {
  1319.                 s -= 8;
  1320.                 if (a2 > 0) s -= 6;
  1321.               }
  1322.             if (PawnCnt[black][column] == 0)
  1323.               {
  1324.                 dw = distance(loc,wking);
  1325.                 db = distance(loc,bking);
  1326.                 s += stage2*(db-dw);
  1327.                 if (side == white) r = rank-1; else r = rank;
  1328.                 if (row[bking] >= r && db < 8-r) in_square = true;
  1329.                   else in_square = false;
  1330.                 e = 0; 
  1331.                 for (a = loc+8; a < 64; a += 8)
  1332.                   if (atak[black][a] == pawn) a = 99;
  1333.                   else if (atak[black][a] > 0 || piece_color[a] != neutral) e = 1; 
  1334.                 if (a == 99) s += stage1*passed_pawn3[rank];
  1335.                 else if (in_square || e == 1) s += stage1*passed_pawn2[rank];
  1336.                 else s += stage1*passed_pawn1[rank];
  1337.               }
  1338.           }
  1339.         else if (piece == pawn && c1 == black)
  1340.           {
  1341.             if (column == 3 || column == 4)
  1342.               if (rank == 6)
  1343.                 {
  1344.                   s -= 10;
  1345.                   if (piece_color[loc-8] == black) s -= 10;
  1346.                 }
  1347.               else if (rank == 3 && a1 == pawn) s += 8;
  1348.             if (column-cbking > 1 || cbking-column > 1) s += stage1*(7-rank);
  1349.             if (PawnCnt[black][column] > 1) s -= 12;
  1350.             if (column > 0 && PawnCnt[black][column-1] == 0 &&
  1351.                 column < 7 && PawnCnt[black][column+1] == 0) s -= 24;
  1352.             if (a1 != pawn && atak[c1][loc-8] != pawn)
  1353.               {
  1354.                 s -= 8;
  1355.                 if (a2 > 0) s -= 6;
  1356.               }
  1357.             if (PawnCnt[white][column] == 0)
  1358.               {
  1359.                 dw = distance(loc,wking);
  1360.                 db = distance(loc,bking);
  1361.                 s += stage2*(dw-db);
  1362.                 if (side == black) r = rank+1; else r = rank;
  1363.                 if (row[wking] <= r && dw < r+1) in_square = true;
  1364.                   else in_square = false;
  1365.                 e = 0; 
  1366.                 for (a = loc-8; a >= 0 ; a -= 8)
  1367.                   if (atak[white][a] == pawn) a = -99;
  1368.                   else if (atak[white][a] > 0 || piece_color[a] != neutral) e = 1; 
  1369.                 if (a == -99) s += stage1*passed_pawn3[7-rank];
  1370.                 else if (in_square || e == 1) s += stage1*passed_pawn2[7-rank];
  1371.                 else s += stage1*passed_pawn1[7-rank];
  1372.               }
  1373.           }
  1374.         else if (piece == knight)
  1375.           {
  1376.             s = pknight[loc];
  1377.           }
  1378.         else if (piece == bishop)
  1379.           {
  1380.             s += pbishop[loc];
  1381.           }
  1382.         else if (piece == rook)
  1383.           {
  1384.             if (PawnCnt[white][column] == 0) s += 6;
  1385.             if (PawnCnt[black][column] == 0) s += 6;
  1386.           }
  1387.         else if (piece == queen)
  1388.           {
  1389.             s = s/3;
  1390.           }
  1391.         else if (piece == king)
  1392.           {
  1393.             m0 = map[loc];
  1394.             if (castld[c1]) s += (20/(stage1+1));
  1395.             else if (kingmoved[c1] > 0) s -= (30/(stage1+1));
  1396.             if (emtl[c1] > 1300)
  1397.               {
  1398.                 s -= 2*edge[loc]; a = 0;
  1399.                 for (j = Dstart[king]; j <= Dstop[king]; j++)
  1400.                   if ((u = unmap[m0+Dir[j]]) >= 0)
  1401.                     {
  1402.                       if (atak[c2][u] > 0) a++;
  1403.                       if (board[u] == pawn) s += 5;
  1404.                     }
  1405.                 if (a > 1) s -= 5*a; 
  1406.                 if (column > 0 && PawnCnt[c1][column-1] == 0) s -= 10;
  1407.                 if (column < 7 && PawnCnt[c1][column+1] == 0) s -= 10;
  1408.                 if (PawnCnt[c1][column] == 0) s -= 12;
  1409.               }
  1410.             else
  1411.               {
  1412.                 e = edge[loc];
  1413.                 for (j = Dstart[king]; j <= Dstop[king]; j++)
  1414.                   if ((u=unmap[m0+Dir[j]]) >= 0)
  1415.                     if (atak[c2][u] == 0) e += edge[u];
  1416.                 s += (e*((1300-emtl[c1])/100))/8;
  1417.               }
  1418.             if (mtl[c1]<1000 && mtl[c2]<1990 && distance(wking,bking)==2
  1419.                 && e<12) s -= 30;
  1420.           }
  1421.         if (a2 > 0 && (a1 == 0 || a2 < piece)) ++hung[c1];
  1422.         if (a2 > 0) s -= 3;
  1423.         pscore[c1] += s; svalue[loc] = s;
  1424.       }
  1425.   }
  1426.   if (hung[side] > 1) pscore[side] -= 12;
  1427.   if (hung[xside] == 1) pscore[xside] -= 8;
  1428.   if (hung[xside] > 1) pscore[xside] -= 24;
  1429.   *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] - 5;
  1430.   if (*score > 0 && pmtl[side] == 0 && emtl[side] <= value[bishop])
  1431.     *score = 0;
  1432.   if (*score < 0 && pmtl[xside] == 0 && emtl[xside] <= value[bishop])
  1433.     *score = 0;
  1434. }
  1435.  
  1436.  
  1437. CaptureSearch(side,xside,ply,depth,alpha,beta,qscore,best,bstline)
  1438. short side,xside,ply,depth,alpha,beta,qscore,*best;
  1439. unsigned short bstline[];
  1440.  
  1441. /*
  1442.     Perform alpha-beta search on captures up to 9 ply past
  1443.     nominal search depth.
  1444. */
  1445.  
  1446. {
  1447. register short j,f,t;
  1448. short v,q,pnt,tempb,tempc,pbst,sv;
  1449. unsigned short nxtline[30];
  1450. struct leaf *node;
  1451.  
  1452.   *best = -qscore; bstline[ply] = 0;
  1453.   CaptureList(side,xside,ply);
  1454.   pnt = TrPnt[ply]; pbst = 0;
  1455.   while (pnt < TrPnt[ply+1] && *best <= beta)
  1456.     {
  1457.       node = &Tree[pnt]; pnt++;
  1458.       f = node->f; t = node->t;
  1459.       v = value[board[t]]-qscore+svalue[t]; 
  1460.       if (v > alpha)
  1461.         {
  1462.           if (board[t] == king) node->score = 10000;
  1463.           else if (depth == 1) node->score = v;
  1464.           else
  1465.             {
  1466.               ykillr = t; NodeCnt++;
  1467.               sv = svalue[t]; svalue[t] = svalue[f];
  1468.               tempb = board[t]; tempc = piece_color[t];
  1469.               UpdatePieceList(tempc,t,1);
  1470.               board[t] = board[f]; piece_color[t] = piece_color[f];
  1471.               indx[t] = indx[f]; PieceList[side][indx[t]] = t;
  1472.               board[f] = no_piece; piece_color[f] = neutral;
  1473.               CaptureSearch(xside,side,ply+1,depth-1,-beta,-alpha,v,
  1474.                             &q,nxtline);
  1475.               node->score = -q;
  1476.               board[f] = board[t]; piece_color[f] = piece_color[t];
  1477.               indx[f] = indx[t]; PieceList[side][indx[f]] = f;
  1478.               board[t] = tempb; piece_color[t] = tempc;
  1479.               UpdatePieceList(xside,t,2);
  1480.               svalue[f] = svalue[t]; svalue[t] = sv;
  1481.             }
  1482.         if (node->score > *best)
  1483.           {
  1484.             pbst = pnt;
  1485.             *best = node->score;
  1486.             if (*best > alpha) alpha = *best;
  1487.             for (j = ply; j < 30; j++) bstline[j] = nxtline[j];
  1488.             bstline[ply] = (f<<8) + t;
  1489.           } 
  1490.         }
  1491.     }
  1492.   if (pbst == 0) Ckillr[side] = -1;
  1493.     else Ckillr[side] = (Tree[pbst].f<<8) + Tree[pbst].t;
  1494. }
  1495.  
  1496.  
  1497. expand(side,node,depth,ply,alpha,beta,nxtline)
  1498. short side,depth,alpha,beta,ply;
  1499. unsigned short nxtline[];
  1500. struct leaf *node;
  1501.  
  1502. /*
  1503.     Generate a score for current position by calling search routine
  1504.     to generate opponents best response.
  1505. */
  1506.  
  1507. {
  1508. short s,xside;
  1509. struct leaf *reply;
  1510.  
  1511.   xside = otherside[side];
  1512.   nxtline[ply] = (node->f<<8) + node->t;
  1513.   nxtline[ply+1] = node->reply;
  1514.   search(xside,ply+1,depth-1,-beta,-alpha,nxtline);
  1515.   if (!timeout)
  1516.     {
  1517.       reply = &Tree[TrPnt[ply+1]];
  1518.       s = -reply->score;
  1519.       if (s >= alpha && s <= beta) node->score = s;
  1520.       else if (s < alpha && s < node->score) node->score = s;
  1521.       else if (s > beta && s > node->score) node->score = s;
  1522.       if ((reply->flags & incheck) && !(node->flags & check))
  1523.         {
  1524.           node->flags |= draw; node->score = 0;
  1525.         }
  1526.       if ((node->flags & draw) || (node->score <= -9000) ||
  1527.           (node->score >= 9000)) node->flags |= exact;
  1528.       node->reply = nxtline[ply+1];
  1529.     }
  1530. }
  1531.  
  1532.  
  1533. evaluate(side,node,ply,depth,alpha,beta,nxtline)
  1534. short side,ply,alpha,beta;
  1535. unsigned short nxtline[];
  1536. struct leaf *node;
  1537.  
  1538. /*
  1539.     See if either king is in check.  If positional score estimate
  1540.     passed forward from previous ply warrants, score the position.
  1541.     If positional score is greater than alpha, perform CaptureSearch
  1542.     to modify score based on ensuing capture sequence.
  1543. */
  1544.  
  1545. {
  1546. short xside,s,x,t;
  1547.  
  1548.   hung[white] = hung[black] = 0;
  1549.   xside = otherside[side];
  1550.   ataks(xside,atak[xside]);
  1551.   if (atak[xside][PieceList[side][0]] > 0)
  1552.     {
  1553.       node->score = ply-10000;
  1554.       node->flags |= incheck;
  1555.       node->flags |= exact;
  1556.     }
  1557.   else
  1558.     {
  1559.       ataks(side,atak[side]);
  1560.       if (atak[side][PieceList[xside][0]]) node->flags |= check;
  1561.       if (ply > Sdepth) t = 0; else t = 90;
  1562.       s = -PPscore[ply-1]+mtl[side]-mtl[xside];
  1563.       if (s+t > alpha || (node->flags & check) ||
  1564.         (node->flags & pwnthrt)) ScorePosition(side,&s);
  1565.       PPscore[ply] = s-mtl[side]+mtl[xside];
  1566.       if (s < alpha || depth > 1)
  1567.         {
  1568.           if (node->score < -12000) node->score = s;
  1569.         }
  1570.       else
  1571.         {
  1572.           ykillr = xkillr;
  1573.           CaptureSearch(xside,side,ply+1,9,-s-1,-alpha,s,&x,nxtline);
  1574.           node->score = -x;
  1575.           node->reply = nxtline[ply+1];
  1576.         }
  1577.       repetition(node);
  1578.     }
  1579. }
  1580.  
  1581.  
  1582. search(side,ply,depth,alpha,beta,bstline)
  1583. short side,ply,depth,alpha,beta;
  1584. unsigned short bstline[];
  1585.  
  1586. /*
  1587.     Perform the main alpha-beta search.  Extensions up to 3 ply
  1588.     beyond the nominal iterative search depth MAY occur for checks,
  1589.     check evasions, pawn promotion threats, and threats to multiple
  1590.     pieces.  
  1591. */
  1592.  
  1593. {
  1594. register short j;
  1595. short best,tempb,tempc,xside,pnt,pbst,hhh,d;
  1596. unsigned short mv,nxtline[30];
  1597. struct leaf *node;
  1598.  
  1599.   xside = otherside[side];
  1600.   if (ply == 1) InChk = false; else InChk = ChkFlag[ply-1];
  1601.   PV = bstline[ply];
  1602.   if (ply < 3)
  1603.     {
  1604.       Swag1 = Swag2 = 0;
  1605.     }
  1606.   else
  1607.     {
  1608.       Swag1 = (Tree[TrPnt[ply-2]].f<<8) + Tree[TrPnt[ply-2]].t;
  1609.       Swag2 = (Tree[TrPnt[ply-2]+1].f<<8) + Tree[TrPnt[ply-2]+1].t;
  1610.     }
  1611.   if (ply > 1) MoveList(side,ply);
  1612.   best = -12000; PPscore[ply] = -PPscore[ply-1];
  1613.   pnt = TrPnt[ply]; pbst = pnt;
  1614.   while (pnt < TrPnt[ply+1] && best<=beta && !timeout)
  1615.     {
  1616.       node = &Tree[pnt]; NodeCnt++;
  1617.       nxtline[ply+1] = 0;
  1618.       if (ply == 1)
  1619.         {
  1620.           d = node->score-best;
  1621.           if (pnt == TrPnt[ply]) extra_time = 0;
  1622.           else if (d < -50) extra_time = -response_time/3;
  1623.           else if (d < 20) extra_time = 0;
  1624.           else if (d < 60) extra_time = response_time/3;
  1625.           else if (d < 200) extra_time = response_time;
  1626.           else extra_time = 2*response_time;
  1627.         }
  1628.       if (node->flags & capture) CptrFlag[ply] = true;
  1629.         else CptrFlag[ply] = false;
  1630.       if (node->flags & pwnthrt) PawnThreat[ply] = true;
  1631.         else PawnThreat[ply] = false;
  1632.       if (ply == 1 && post)
  1633.         {
  1634.           algbrnot(node->f,node->t);
  1635.           gotoXY(50,2); printw("%5s",mvstr1,' '); ClrEoln();
  1636.         }
  1637.       if ((node->flags & exact) == 0)
  1638.       {
  1639.         MakeMove(side,node,&tempb,&tempc);
  1640.         evaluate(side,node,ply,depth,alpha,beta,nxtline);
  1641.         if (hung[xside] > 1 && ply <= Sdepth) hhh = true;
  1642.           else hhh = false;
  1643.         if (node->flags & check) ChkFlag[ply] = true; 
  1644.           else ChkFlag[ply] = false;
  1645.         if ((node->flags & exact) == 0)
  1646.           {
  1647.             if (depth > 1) expand(side,node,depth,ply,alpha,beta,nxtline);
  1648.             if (node->score <= beta && (PawnThreat[ply] ||
  1649.                ((ChkFlag[ply] || hhh) && depth == 1)))
  1650.               expand(side,node,depth+1,ply,alpha,beta,nxtline);
  1651.             else if ((ChkFlag[ply-1] || PawnThreat[ply-1]) &&
  1652.                      ply<=Sdepth+2 && Sdepth>1 &&
  1653.                      (ply>Sdepth || CptrFlag[ply-1] ||
  1654.                      (ply>3 && (ChkFlag[ply-3] || CptrFlag[ply-3])) ||
  1655.                      (hung[side] > 1)))
  1656.               expand(side,node,depth+1,ply,alpha,beta,nxtline);
  1657.           }
  1658.         UnmakeMove(side,node,&tempb,&tempc);
  1659.       }
  1660.       if (node->score > best && !timeout)
  1661.         {
  1662.           if (ply == 1 && depth > 1 && node->score>alpha &&
  1663.             (node->flags & exact) == 0) node->score += 5;
  1664.           best = node->score; pbst = pnt;
  1665.           if (best > alpha) alpha = best;
  1666.           for (j = ply; j < 30; j++) bstline[j] = nxtline[j];
  1667.           bstline[ply] = (node->f<<8) + node->t;
  1668.           if (ply == 1 && post) post_move(node);
  1669.         }
  1670.       if ((pnt % 5) == 0) ElapsedTime(0);
  1671.       pnt++;
  1672.       if (best > 9000) beta = 0;
  1673.     }
  1674.   if (timeout) pnt--;
  1675.   if (ply == 1) sort(TrPnt[ply],pnt-1);
  1676.   else Tree[TrPnt[ply]] = Tree[pbst];
  1677.   node = &Tree[TrPnt[ply]];
  1678.   mv = (node->f<<8) + node->t;
  1679.   if (node->t != (GameList[GameCnt] & 0x00FF))
  1680.     if (best > beta) killr1[ply] = mv;
  1681.     else if (mv != killr2[ply])
  1682.       {
  1683.         killr3[ply] = killr2[ply];
  1684.         killr2[ply] = mv;
  1685.       }
  1686.   if (InChk && best > -9000) Qkillr[ply] = mv;
  1687. }
  1688.  
  1689.